package framework.classification.entities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import framework.AnnuaireCocola;
import framework.classification.entities.lattice.TreillisI;
import framework.classification.library.AbstractClassfication;
import framework.entity.ACLEntity;
import framework.entity.ACLFunction;
import framework.entity.ACLInterface;

public class ClInterfaceRequired extends ClAbstractEntity {


	public static String INTERFACE_REQUIRED = "Interface_Required";
	
	private ArrayList<ACLInterface> interfaces;

	private HashMap<String,ArrayList<String>> interNoFunction;

	public ClInterfaceRequired(String s, AbstractClassfication cl,TreillisI t, ArrayList<ACLInterface> inter) {
		super(s, cl, t);
		interNoFunction = new HashMap<String,ArrayList<String>>();
		interfaces = inter;
		createTableModel();
		int x = getAttribut().size();
		int y = getEntity().size();
		table = new int[x][y];

		calculPair();

	}

	public void createTableModel() {


		ArrayList<String> maxEntities = new ArrayList<String>();

		// on ajoute toutes les interfaces dans les lignes
		for (ACLInterface inter : interfaces){
			getEntity().add(inter.getName());
		}
		//on ajoute les fonctions fourni des interfaces dans les colonnes
		// ainse que les nouvelles fonctions deduite 
		for (ACLInterface inter : interfaces){
			ArrayList<ACLFunction> functions = inter.getFunctions();
			for (ACLFunction func : functions){

				//on recupere la classification de la fonction correspondante
				ClFunctionRequired clfunc = cl.getFunctionRequired().get(func.toString());
				
				//on ajoute les fonctions abstraite
				for (String absfunc : clfunc.getAbstractReduced().keySet()){
					ACLFunction f = new ACLFunction(absfunc,ACLFunction.MODE2);
					if (!getAttribut().contains(f.toString()))
						getAttribut().add(f.toString());
				}
				//on ajoute les fonctions reel
				for (String realfunc : clfunc.getRealReduced().keySet()){
					ACLFunction f = new ACLFunction(realfunc,ACLFunction.MODE2);
					
					if (!getAttribut().contains(f.toString()))
						getAttribut().add(f.toString());

					String mf = clfunc.getLattice().getMaxSuperEntity();
					if (!maxEntities.contains(mf))
						maxEntities.add(mf);
				}


			}

		}

		//on verifie que toutes les interface possédent tous les types de fonctions
		//Sinon on rajoute la negation de la fonction non incluse d'une fonction par une interface
		//et on sauvegarde le couple interface fonction pour ne pas avoir à le recalculer
		

		for (ACLInterface inter : interfaces){
			ArrayList<ACLFunction> functions = inter.getFunctions();
			for (String max : maxEntities){
				Boolean add = true;
				for (ACLFunction func : functions){
					//on recupere la classification de la fonction correspondante
					ClFunctionRequired clfunc = cl.getFunctionRequired().get(func.toString());
					if (max.equals(clfunc.getLattice().getMaxSuperEntity())){
						add =false;

					}
				}
				if (add){
						if (!interNoFunction.containsKey(inter.getName()))
							interNoFunction.put(inter.getName(),new ArrayList<String>());
						if (!interNoFunction.get(inter.getName()).contains("!"+max));
							interNoFunction.get(inter.getName()).add("!"+max);

						if (!getAttribut().contains("!"+max))
							getAttribut().add("!"+max);
				}
			}

		}
	}

	public void calculPair() {
		for (int x = 0; x < this.getAttribut().size(); x++) {
			for (int y = 0; y < this.getEntity().size(); y++) {

				if (isPair(getAttribut().get(x), getEntity().get(y), y))
					table[x][y] = 1;
				else if (table[x][y] == 0)
					table[x][y] = 0;

			}
		}
	}

	public Boolean isPair(String func,String inter, int y) {
		
		if (func.charAt(0) == '!'){
			if (interNoFunction.containsKey(inter)){
				ArrayList<String> nofuncs = interNoFunction.get(inter);
				if (nofuncs.contains(func)){
					int indexfunc = getAttribut().indexOf(func.substring(1));
					table[indexfunc][y] = 1;
					return true;
					
				}
				
			}
				
			return false;
		}
		else{
		
		//on recupere la classification de la fonction func
		ClFunctionRequired clFunc = getAbstractClassfication().getFunctionRequired().get(func);
		
		ArrayList<ACLFunction> functions = getAbstractClassfication().getStructure().getInterfacesFonction().get(inter);
		
		for (ACLFunction funcinter : functions){
			
			if (clFunc.getLattice().isParent(func,funcinter.toString())){
			
				return true;
			}
		
		}
		return false;
		}
	}

	

	@Override
	public String getType() {
		// TODO Auto-generated method stub
		return INTERFACE_REQUIRED;
	}

	@Override
	public ACLEntity getACLEntity(String s) {
		// TODO Auto-generated method stub
		return null;
	}



}
